#include <sys/shm.h>

#include "shm_com.h"

int main()
{
	int running = 1;
	void * shared_memory = (void*)0;
	struct share_use_st * shared_stuff;

	int shmid;

	srand((unsigned int) getpid());

	shmid = shmget((key_t)1234,sizeof(struct share_use_st), 0666 | IPC_CREAT);//创建共享内存
	
       	/* 函数原型：int shmget(key_t key,size_t size,int shmflg) ;
	 * 和信号量一样，程序需要提供一个参数key，它有效的为共享内存段命名，shmget函数返回一个共享内存标识符，该标识符用于后续的共享内存函数。
	 * arg2:以字节为单位指定需要共享的内存单元。
	 * arg3:shmflg包含9个bit的权限标志，它们的作用与创建信号量时使用的mode标志一样，由IPC_CREAT定义的一个特殊bit必须和权限标志安装或才能创建一个新的共享内存段。权限标志的设定，可以有效的对数据进行只读访问的效果。猜测：权限标志的设置如同于文件权限，比如上面设置的任何人可读可写的权限。
	 * 如果共享内存创建成功，shmget返回一个非负整数，即共享内存标识符；反之，返回-1
	 * */
	
	if (shmid == -1 ) {
		fprintf(stderr,"Shmget Failed\n");
		exit (EXIT_FAILURE);
	}

	shared_memory = shmat(shmid, NULL, 0);//使用标志符访问共享内存。
	/*
	 * 第一次创建共享内存段时，它不能被任何进程访问。要想启用对该共享内存的访问，必须将其连接到一个进程的地址空间中。这项工作由shmat函数完成。
	 * 原型：void * shmat(int shm_id,const void * shm_addr,int shmflg);//标识符，地址，操作标识。
		 * 标识符,shm_id是由shmget返回的共享标识符
		 * shm_addr指定的是共享内存连接到目前进程中的地址位置。它通常是一个空指针，表示让系统来选择共享内存出现的地址。
		 * shmflg是一组位标志，有两个取值，但不常用。
	 * 返回：如果调用成功，它返回一个指向共享内存第一个字节的指针；反之返回-1。
	 * 共享内存的读写权限由它的所有者（共享内存的创建者）、它的访问权限和当前进程的所有者决定。
	 * */
	if (shared_memory == (void *)-1) {
		fprintf(stderr,"Shmat Failed\n");
		exit(EXIT_FAILURE);
	}
	//printf("Memory Attached at %lX\n",(long) shared_memory);
	printf("Memory Attached at %lX\n",(intptr_t) shared_memory);//intptr_t 是在stdint.h中定义的一个变数型宏，可以在不同的机器上用不同的类型，在32bit机器上intptr_t不变，在64bit上intptr_t则变为long int.
	
	shared_stuff = (struct share_use_st *)shared_memory;
	shared_stuff->written_by_you = 0;
	while (running) {
		if (shared_stuff->written_by_you) {
			printf("You wrote:[%s]\n",shared_stuff->some_text);
			sleep( rand() % 4);
			shared_stuff->written_by_you = 0;
			if (strncmp(shared_stuff->some_text,"end",3) == 0) {
				running = 0;
			}
		}
	}

	if (shmdt(shared_memory) == -1) {
		fprintf(stderr,"Shmdt Failed\n");
		exit(EXIT_FAILURE);
	}//分离共享内存

	if (shmctl(shmid, IPC_RMID, 0) == -1) {
		fprintf(stderr,"Shmctl(IPC_RMID) Failed\n");
		exit (EXIT_FAILURE);
	}//删除共享内存段
	/*
	 * 第三个参数buf是一个指针，它执行包含共享内存模式和访问权限的结构。
	 * */
	printf("Client Bye bye\n");
	exit (EXIT_SUCCESS);
}
